#include "ConfirmView.hpp"

using namespace BFT::order::messages;

ConfirmView::ConfirmView(uint32_t _view, uint32_t _seqno, 
			boost::shared_ptr<BFT::messages::HistoryDigest> _history,
			uint32_t _sendingReplica)
	: BFT::messages::MacArrayMessage(CONFIRM_VIEW, computeSize(), 
					_sendingReplica, BFT::Parameters::getOrderCount())
{
	view = _view;
	seqNo = _seqno;
	history = _history;
	
	int offset = getOffset();
	int bytes_size;
	boost::shared_ptr<char> bytes = getBytes(bytes_size);
	
	//write down the view number
	*(uint32_t*)(bytes.get()+offset) = htonl(view);
	offset += VIEW_NUMBER_SIZE;
	
	//write down the sequence number
	*(uint32_t*)(bytes.get()+offset) = htonl(seqNo);
	offset += SEQUENCE_NUMBER_SIZE;
	
	//write down the history
	memcpy( (void*)(bytes.get()+offset) , (const void*)(history.get()->getBytes().get()) , DIGEST_SIZE );
}

ConfirmView::ConfirmView(boost::shared_ptr<char> _bytes, int _bytes_size)
	: BFT::messages::MacArrayMessage(_bytes, _bytes_size)
{
	if (getTag() != CONFIRM_VIEW)
	{
		fprintf(stderr,"unable to build a confirmview from bytes, wrong tag\n");
		exit(156);
	}
	
	int offset = getOffset();
	
	//read the view number
	view = ntohl( *(uint32_t*)(_bytes.get()+offset) );
	offset += VIEW_NUMBER_SIZE;
	
	//read the sequence number
	seqNo = ntohl( *(uint32_t*)(_bytes.get()+offset) );
	offset += SEQUENCE_NUMBER_SIZE;
	
	//read the history digest
	boost::shared_ptr<char> history_bytes ( (char*)malloc(DIGEST_SIZE));
	memcpy( (void*)(history_bytes.get()) , (const void*)(_bytes.get()+offset) , DIGEST_SIZE );
	offset += DIGEST_SIZE;
	history = BFT::messages::HistoryDigest::fromBytes(history_bytes, DIGEST_SIZE);
	
	if( (unsigned int)offset != _bytes_size - getAuthenticationSize())
	{
		fprintf(stderr, "trying to build a ConfirmView from invslid bytes\n");
		exit(157);
	}
}

bool ConfirmView::matches(boost::shared_ptr<BFT::order::messages::ConfirmView> _other_cv)
{
	return view == _other_cv.get()->getViewNo() &&
		 seqNo == _other_cv.get()->getSeqNo() &&
		 history.get()->equals(_other_cv.get()->getHistory());
}

bool ConfirmView::equals(boost::shared_ptr<BFT::order::messages::ConfirmView> _other_cv)
{
	return matches(_other_cv) && BFT::messages::MacArrayMessage::equals(_other_cv);
}

uint32_t ConfirmView::computeSize()
{
	return VIEW_NUMBER_SIZE +
		SEQUENCE_NUMBER_SIZE + 
		DIGEST_SIZE;
}
